package br.edu.ufcg.compiladores.brasigol.geracao;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.TreeSet;

/**
 * @author Marcelo Emanoel
 * 
 */
public class GeradorDeCodigo {
	private File arquivoCod;

	private File arquivoDat;

	private Collection<LinhaDeCodigo> linhas;

	private int numeroDeBytesOcupados;

	/**
	 * @return the numeroDeBytesOcupados
	 */
	private int getNumeroDeBytesOcupados() {
		return numeroDeBytesOcupados;
	}

	/**
	 * @param numeroDeBytesOcupados
	 *            the numeroDeBytesOcupados to set
	 */
	public void setNumeroDeBytesOcupados(int numeroDeBytesOcupados) {
		this.numeroDeBytesOcupados = numeroDeBytesOcupados;
	}

	public GeradorDeCodigo(File arquivoFonte) {
		String nomeArquivo = arquivoFonte.getName();
		String nome = nomeArquivo.substring(0, nomeArquivo.lastIndexOf("."));
		setArquivoCod(new File(arquivoFonte.getParent()+"/"+nome + ".cod"));
		setArquivoDat(new File(arquivoFonte.getParent()+"/"+nome + ".dat"));
		setLinhas(new TreeSet<LinhaDeCodigo>());
	}

	public void addLinha(LinhaDeCodigo linha) {
		getLinhas().add(linha);
	}

	public void removeLinha(LinhaDeCodigo linha) {
		getLinhas().remove(linha);
	}

	/**
	 * @return Returns the linhas.
	 */
	private Collection<LinhaDeCodigo> getLinhas() {
		return linhas;
	}

	/**
	 * @param linhas
	 *            The linhas to set.
	 */
	private void setLinhas(Collection<LinhaDeCodigo> linhas) {
		this.linhas = linhas;
	}

	/**
	 * @return Returns the arquivoCod.
	 */
	private File getArquivoCod() {
		return arquivoCod;
	}

	/**
	 * @param arquivoCod
	 *            The arquivoCod to set.
	 */
	private void setArquivoCod(File arquivoCod) {
		this.arquivoCod = arquivoCod;
	}

	/**
	 * @return Returns the arquivoDat.
	 */
	private File getArquivoDat() {
		return arquivoDat;
	}

	/**
	 * @param arquivoDat
	 *            The arquivoDat to set.
	 */
	private void setArquivoDat(File arquivoDat) {
		this.arquivoDat = arquivoDat;
	}

	public void gerar() {
		PrintWriter writer = null;
		try {
			writer = new PrintWriter(getArquivoCod());
			for (LinhaDeCodigo linha : getLinhas()) {
				writer.println(linha);
			}
			geraDat();
		} catch (FileNotFoundException exception) {
			exception.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			writer.flush();
			writer.close();
		}
	}

	public LinhaDeCodigo makeLinha() {
		LinhaDeCodigo linha = new LinhaDeCodigo();
		linha.setNumeroDaLinha(getLinhas().size());
		addLinha(linha);
		return linha;
	}

	public int posicao() {
		return getLinhas().size();
	}

	private void geraDat() throws IOException {
		getArquivoDat().createNewFile();
		FileOutputStream stream = new FileOutputStream(getArquivoDat());
		byte[] array = new byte[getNumeroDeBytesOcupados()];
		stream.write(array);
		stream.flush();
		stream.close();
	}
}